package com.leo.customer.controller

import com.leo.customer.entity.dao.UserDao
import com.leo.customer.entity.dao.UserRoleDao
import com.leo.customer.entity.pojo.AuthenticatePo
import com.leo.customer.entity.pojo.User
import com.leo.customer.entity.pojo.UserRole
import com.leo.customer.entity.pojo.UserVo
import com.leo.customer.service.UserService
import com.leo.customer.utils.getUser
import com.leo.result.ResultCode
import com.leo.result.ResultEntity
import io.swagger.annotations.Api
import org.springframework.beans.BeanUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.jpa.domain.Specification
import org.springframework.web.bind.annotation.*
import javax.persistence.criteria.JoinType
import javax.persistence.criteria.Predicate
import javax.servlet.http.HttpServletRequest
import javax.validation.Valid

@Api("用户接口", tags = ["用户接口"])
@RestController
@RequestMapping("user")
class UserController {

    @Autowired
    lateinit var userService: UserService

    @Autowired
    lateinit var userRoleDao: UserRoleDao

    @Autowired
    lateinit var userDao: UserDao


    /**
     * 用户注册
     * @param user User
     * @param request HttpServletRequest
     * @return ResultEntity<UserVo>
     */
    @PostMapping("register")
    public fun registerUser(@RequestBody @Valid user: User, request: HttpServletRequest):
            ResultEntity<UserVo> {
        val userByPhone = userDao.findUserByPhone(user.phone)
        if (userByPhone != null) {
            return ResultEntity.fail(ResultCode.PhoneExists)
        }
        return ResultEntity.success(userService.register(user))
    }

    /**
     * 用户登录
     * @param request HttpServletRequest
     * @param user User
     * @return ResultEntity<User>
     */
    //    @UserLoginToken
    @PostMapping("login")
    fun login(request: HttpServletRequest, @RequestBody @Valid user: User): ResultEntity<User> {
        val userByPhone = userDao.findUserByPhone(user.phone)
        return if (userByPhone == null) {
            ResultEntity.fail(ResultCode.UserNotExist)
        } else {
            ResultEntity.success(userByPhone)
        }
    }

    /**
     * 用户认证接口
     * @param authenticatePo AuthenticatePo
     * @param request HttpServletRequest
     * @return ResultEntity<User>
     */
    @PostMapping("auth")
    fun authenticate(
        @RequestBody @Valid authenticatePo: AuthenticatePo,
        request: HttpServletRequest
    ): ResultEntity<User> {
        val user = request.getUser()
        //未认证
        return if (!user.hasAuthenticate()) {
            user.identityNumber = authenticatePo.identityNumber
            user.userName = authenticatePo.realName
            val save = userDao.save(user)
            ResultEntity.success(save)
        } else {
            ResultEntity.fail(ResultCode.HasAuthenticate)
        }
    }


    /**
     * 获取用户权限
     * @param id Int
     * @return MutableList<User>
     */
    @GetMapping("getRole")
    public fun getUsersByRole(@RequestParam id: Int): MutableList<User> {
        val specification: Specification<User> = Specification { root, query, cb ->
            val pres = mutableListOf<Predicate>()
            val join = root.join<User, UserRole>("userRoles", JoinType.LEFT)
            pres.add(cb.equal(join.get<Int>("id"), id))
            val toTypedArray = pres.toTypedArray()
            return@Specification cb.and(*toTypedArray)
        }
        return userDao.findAll(specification)
    }

    /**
     * 设置用户权限
     * @param id Int
     * @return UserVo
     */
    @GetMapping("setRole")
    public fun setUserRole(@RequestParam id: Int): UserVo {
        val one: User = userDao.getOne(id)
        val role: UserRole = userRoleDao.getOne(1)
        one.userRoles.add(role)
        val saveAndFlush = userDao.saveAndFlush(one)
        val userVo = UserVo()
        BeanUtils.copyProperties(saveAndFlush, userVo)
        return userVo
    }

    /**
     * 删除用户权限
     * @param id Int
     * @return MutableList<User>
     */
    @GetMapping("deleteRole")
    public fun deleteRole(@RequestParam id: Int): MutableList<User> {
        val users = getUsersByRole(1)
        users.forEach { user ->
            run {
                if (user.id == id) {
                    user.userRoles.removeIf { t: UserRole ->
                        t.id == id
                    }
                    userDao.saveAndFlush(user)
                }
            }
        }
        return users
    }
    //endregion
}
